import datetime
import re

from spiders.base import BaseSpider
from utils.log import logger
from exceptions import SpiderErrorToEnd,SpiderErrorToRetry
from utils.tools import format_date


class MercadolibreSpider(BaseSpider):
    async def login(self):
        # await self.page.goto("https://myaccount.mercadolibre.com.mx/")
        ...
        # todo 处理login

    async def get_preloaded_state(self):
        return await self.page.evaluate("window.__PRELOADED_STATE__")

    async def submit_appointment(
            self,
            token,
            inbound_id,
            selected_shipment_type,
            selected_appointment,
            selected_warehouse
    ):
        resp = await self.fetch_api.async_post(
            self.page,
            f"/api/shipping/inbounds/{inbound_id}/appointment",
            headers={"x-csrf-token": token},
            json={
                "selected_shipment_type": self.shipping_types[selected_shipment_type - 1],
                "selected_appointment": selected_appointment,
                "selected_warehouse": selected_warehouse
            }
        )
        return resp.json()

    def find_available_slot(self, slots, date, start_time, end_time):

        start = format_date(f"{date} {start_time}", "%Y-%m-%d %H:%M")
        end = format_date(f"{date} {end_time}", "%Y-%m-%d %H:%M")

        d = format_date(date, '%Y-%m-%d')
        for slot in slots:
            slot_date = format_date(slot['day'], '%Y-%m-%d')
            if d == slot_date:
                if not slot['available_slots']:
                    break
                else:
                    for available in slot['available_slots']:
                        slot_date = format_date(available['slot_date'], '%Y-%m-%dT%H:%M:%S-06:00')
                        if start < slot_date < end:
                            return available
                break
        return None

    def find_all_available_date(self, slots):
        for slot in slots:
            if not slot['available_slots']:
                continue
            for available_slot in slot['available_slots']:
                d = format_date(available_slot['slot_date'], '%Y-%m-%dT%H:%M:%S-06:00')
                yield d.strftime("%Y-%m-%d %H:%M")

    @property
    def shipping_types(self):
        return ['pickup', 'ftl', 'supplier']

    async def shipping_inbounds(
            self,
            url,
            shipping_type,
            date,
            start_time,
            end_time,
            **kwargs
    ):
        await self.page.goto(url)
        token_element = self.page.locator('[name="csrf-token"]')
        await token_element.wait_for(timeout=5000, state="hidden")
        if await token_element.count():
            token = await token_element.get_attribute("content")
            preloaded_state = await self.get_preloaded_state()
            if not preloaded_state:
                # todo 没有预约界面，无法预约
                raise SpiderErrorToEnd("没有预约界面，无法预约")
            else:
                inbound_id = re.search("/inbounds/(\d+)/appointment", url).group(1)
                warehouse = preloaded_state['data']['warehouse_data']['id']
                slot = self.find_available_slot(preloaded_state['availability']['slots'], date, start_time, end_time)
                if not slot:
                    logger.warning(f"{inbound_id}:没有可预约的时间")
                    # todo 返回所有可预约的时间
                    available_date = [_ for _ in self.find_all_available_date(preloaded_state['availability']['slots'])]
                    raise SpiderErrorToEnd(f"{inbound_id}:没有可预约的时间")
                data = await self.submit_appointment(
                    token, inbound_id, shipping_type, slot, warehouse
                )
                if data.get("status", "") == "OK":
                    # todo 预约成功
                    logger.success(f"{inbound_id}:预约成功")
        else:
            raise SpiderErrorToRetry("没有获取到token")
